home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
001
/
pibt40s5.arc
/
RECEIVX2.MOD
< prev
next >
Wrap
Text File
|
1987-07-18
|
27KB
|
706 lines
(*----------------------------------------------------------------------*)
BEGIN (* Receive_Xmodem_File *)
(* Open display window for transfer *)
Save_Screen( Saved_Screen );
(* Hide cursor *)
CursorOff;
(* Get protocol name *)
CASE Transfer_Protocol OF
Xmodem_Chk : Tname := 'Xmodem (Checksum)';
Xmodem_Crc : Tname := 'Xmodem (CRC)';
Telink : Tname := 'Telink';
Modem7_Chk : Tname := 'Modem7 (Checksum)';
Modem7_CRC : Tname := 'Modem7 (CRC)';
Xmodem_1K : Tname := 'Xmodem 1K';
Xmodem_1KG : Tname := 'Xmodem 1K G';
Ymodem_Batch : Tname := 'Ymodem Batch';
Ymodem_G : Tname := 'Ymodem G Batch';
WXModem : Tname := 'Windowed XModem';
SeaLink : Tname := 'SEALink';
END (* CASE *);
IF FileName = '' THEN
Menu_Title := 'Receive file using ' + Tname
ELSE
Menu_Title := 'Receive file ' + FileName + ' using ' + Tname;
Draw_Menu_Frame( 15, 10, 78, 22, Menu_Frame_Color, Menu_Title_Color,
Menu_Text_Color, Menu_Title );
Write_Log( Menu_Title, FALSE, FALSE );
Window( 16, 11, 77, 21 );
(* Initialize status display information *)
SOH_Errors := 0;
BlockL_Errors := 0;
BlockN_Errors := 0;
Comple_Errors := 0;
TimeOut_Errors := 0;
Resend_Errors := 0;
CRC_Errors := 0;
Display_Time := FALSE;
Dup_Block := FALSE;
Initialize_Receive_Display;
(* Current sector = 0 *)
Sector_Number := 0;
Sector_Count := 0;
Sector_Prev := 0;
Sector_Length := 128;
(* Overall error count = 0 *)
Error_Count := 0;
(* CRC, WXModem tries *)
CRC_Tries := 0;
WXM_Tries := 0;
(* How long to wait for SOH *)
SOH_Time := Xmodem_Block_Wait;
(* Assume file size not sent *)
Truncate_File := FALSE;
(* Assume file size, date not sent *)
RFile_Size := 0.0;
RFile_Size_2 := 0.0;
RFile_Date := 0.0;
File_Date := 0;
File_Time := 0;
(* Figure if ACKs to be handled *)
Do_ACKs := ( Transfer_Protocol <> Ymodem_G ) AND
( Transfer_Protocol <> Xmodem_1KG );
(* Note if WXModem or SeaLink used *)
Do_WXmodem := ( Transfer_Protocol = WXModem );
Do_SeaLink := ( Transfer_Protocol = SeaLink );
(* Assume file name not sent *)
RFile_Name := '';
(* Assume transfer fails *)
OK_Transfer := FALSE;
(* Assume block 0 not found *)
Block_Zero := FALSE;
(* Starting time *)
Start_Time := TimeOfDay;
(* User intervention flag *)
Alt_R_Pressed := FALSE;
(* Serious error flag *)
Stop_Receive := FALSE;
(* Not null file name *)
Null_File_Name := FALSE;
(* Allocate buffer if requested *)
(* otherwise use sector data area *)
(* directly. *)
IF ( Max_Write_Buffer > 1024 ) AND
( Max_Write_Buffer < MaxBlockAvail ) THEN
BEGIN
Buffer_Length := Max_Write_Buffer;
Long_Buffer := TRUE;
GetMem( Write_Buffer , Buffer_Length );
END
ELSE
BEGIN
Long_Buffer := FALSE;
Buffer_Length := 1024;
Write_Buffer := ADDR( Sector_Data );
END;
(* Determine block starter characters *)
Block_Start_Set := [ ^A, ^B, ^D, ^V, ^X ];
(* No blocks being flushed currently *)
Flush_Count := 0;
(* Empty write buffer *)
Buffer_Pos := 0;
(* Open reception file now if possible *)
RFile_Open := FALSE;
IF FileName <> '' THEN
BEGIN
Open_Receiving_File;
IF Stop_Receive THEN
BEGIN
Cancel_Transfer;
DELAY( Two_Second_Delay );
Restore_Screen( Saved_Screen );
Reset_Global_Colors;
EXIT;
END;
END;
(* Save Xon/Xoff status *)
Save_XonXoff := Async_Do_XonXoff;
Async_Do_XonXoff := Do_WXModem;
(* Begin XMODEM loop *)
REPEAT
(* Reset error flag *)
Error_Flag := FALSE;
Dup_Block := FALSE;
(* Look for SOH *)
REPEAT
IF ( ( Sector_Count = 0 ) AND ( WXM_Tries = 0 ) ) THEN
BEGIN (* Initial handshake *)
Use_CRC := Use_CRC AND ( CRC_Tries < 4 );
Do_WXModem := Do_WXModem AND ( WXM_Tries < 4 );
(* Purge reception *)
Async_Purge_Buffer;
(* Indicate XMODEM type *)
IF Do_WXModem THEN
BEGIN
Async_Send( 'W' );
WXM_Tries := SUCC( WXM_Tries );
END
ELSE
BEGIN
IF ( NOT Do_ACKs ) THEN
Async_Send( 'G' )
ELSE
IF Use_CRC THEN
Async_Send( 'C' )
ELSE
Async_Send( CHR( NAK ) );
CRC_Tries := SUCC( CRC_Tries );
IF Do_Sealink THEN
BEGIN
Async_Send( CHR( 1 ) );
Async_Send( CHR( 254 ) );
END;
END;
IF Display_Status THEN
BEGIN
GoToXY( 1 , 8 );
TextColor( Menu_Text_Color_2 );
IF ( NOT Use_CRC ) THEN
WRITELN(' Checksum errors :')
ELSE
WRITELN(' CRC errors :');
TextColor( Menu_Text_Color );
END;
END (* Initial handshake *);
Wait_For_SOH( SOH_Time, Initial_Ch , Stop_Receive );
(* If CAN found, insist on *)
(* at least two CANs in a row *)
(* before cancelling transfer *)
IF ( Initial_Ch = CAN ) THEN
Wait_For_SOH( SOH_Time, Initial_Ch , Stop_Receive )
(* If EOT and windowing, insist *)
(* on at least two EOTs in a *)
(* row before halting. *)
ELSE IF ( ( Initial_Ch = EOT ) AND
( Do_WXModem OR
( Do_SeaLink AND ( Sector_Count > 0 ) ) ) ) THEN
BEGIN
Async_Send( CHR( NAK ) );
Wait_For_SOH( SOH_Time, Initial_Ch , Stop_Receive )
END
ELSE IF ( Initial_Ch = TimeOut ) THEN
BEGIN
Async_Send( CHR( NAK ) );
Display_Receive_Error( 'Time out, no SOH');
TimeOut_Errors := SUCC( TimeOut_Errors );
END;
(* If WXmodem, leave Xon/Xoff on *)
Async_Do_XonXoff := Do_WXModem;
(* Update status display *)
IF Display_Status THEN
Update_Xmodem_Receive_Display;
(* Update status line *)
IF Do_Status_Line THEN
BEGIN
Set_Status_Line_Name( Short_Terminal_Name );
Write_To_Status_Line( Status_Line_Name, 1 );
END;
UNTIL ( Initial_Ch = SOH ) OR
( Initial_Ch = EOT ) OR
( Initial_Ch = CAN ) OR
( Initial_Ch = SYN ) OR
( Initial_Ch = STX ) OR
( Error_Count > Xmodem_Max_Errors ) OR
( Stop_Receive );
(* Something wrong already -- *)
(* cancel the transfer. *)
IF Stop_Receive THEN
BEGIN
IF NOT Async_Carrier_Detect THEN
BEGIN
Display_Receive_Error('Carrier dropped.');
DELAY( Two_Second_Delay );
END;
END
(* Timed out -- no SOH found *)
ELSE IF Initial_Ch = TimeOut THEN
BEGIN
Display_Receive_Error( 'Time out, no SOH');
TimeOut_Errors := SUCC( TimeOut_Errors );
END
(* SYN found -- possible Telink block *)
(* or WXModem start *)
ELSE IF ( ( Initial_Ch = SYN ) AND Do_WXModem ) THEN
(* Do nothing and skip SYN *)
(* SOH found -- start of XMODEM block *)
(* STX found -- start of Ymodem block *)
(* SYN found -- start of Telink block *)
ELSE IF ( Initial_Ch = SOH ) OR
( Initial_Ch = SYN ) OR
( Initial_Ch = STX ) THEN
BEGIN (* SOH found *)
(* Pick up sector number *)
IF Initial_Ch = STX THEN
Sector_Length := 1024
ELSE
Sector_Length := 128;
IF Do_WXModem THEN
WXModem_Receive_With_TimeOut( Ch )
ELSE
Async_Receive_With_TimeOut( Xmodem_Char_Wait , Ch );
IF Ch = TimeOut THEN
BEGIN
BlockL_Errors := SUCC( BlockL_Errors );
Display_Receive_Error('Short block');
END;
Sector_Number := Ch;
(* Complement of sector number *)
IF Do_WXModem THEN
WXModem_Receive_With_TimeOut( Ch )
ELSE
Async_Receive_With_TimeOut( Xmodem_Char_Wait , Ch );
IF Ch = TimeOut THEN
BEGIN
BlockL_Errors := SUCC( BlockL_Errors );
Display_Receive_Error('Short block');
END;
Sector_Comp := Ch;
(* See if they add up properly *)
IF ( ( Sector_Number + Sector_Comp ) = 255 ) THEN
BEGIN (* Sector number and complement match *)
Sector_Prev1 := SUCC( Sector_Prev );
Block_Zero := ( Sector_Count = 0 ) AND
( Sector_Number = 0 ) AND
( ( Initial_Ch = SYN ) OR
( Transfer_Protocol IN [Xmodem_1K,
Xmodem_1KG,
Ymodem_G,
Ymodem_Batch,
SeaLink] ) );
Use_CRC_2 := Use_CRC AND
( NOT ( Block_Zero AND
( Transfer_Protocol = Telink ) ) );
IF ( Sector_Number = Sector_Prev1 ) OR Block_Zero THEN
BEGIN (* Correct sector found *)
IF Receive_Xmodem_Sector( Use_CRC_2 ) THEN
IF ( NOT Block_Zero ) THEN
BEGIN (* Checksum/CRC OK *)
Write_File_Data;
Error_Count := 0;
Sector_Count := Sector_Count +
( Sector_Length SHR 7 );
Sector_Prev := Sector_Number;
IF Do_ACKs THEN
BEGIN
Async_Send( CHR( ACK ) );
IF Do_WXModem THEN
Async_Send( CHR( Sector_Number AND 3 ) )
ELSE IF Do_SeaLink THEN
BEGIN
Async_Send( CHR( Sector_Number ) );
Async_Send( CHR( Sector_Comp ) );
END;
END;
END (* Checksum/CRC OK *)
ELSE (* Telink/Ymodem/SeaLink block 0 *)
BEGIN
IF ( Initial_Ch = SYN ) OR
( Transfer_Protocol = SeaLink ) THEN
Receive_Telink_Header
ELSE IF ( Transfer_Protocol IN [Xmodem_1K,
Xmodem_1KG,
Ymodem_G,
Ymodem_Batch] ) THEN
Receive_Ymodem_Header;
IF ( NOT Stop_Receive ) THEN
BEGIN
IF ( NOT Do_ACKs ) THEN
Async_Send( 'G' )
ELSE
Async_Send( CHR( ACK ) );
IF Do_WXModem THEN
Async_Send( CHR( Sector_Number AND 3 ) )
ELSE IF Do_SeaLink THEN
BEGIN
Async_Send( CHR( Sector_Number ) );
Async_Send( CHR( Sector_Comp ) );
END;
Error_Count := 0;
END;
END
ELSE
BEGIN (* Checksum/CRC error *)
CRC_Errors := SUCC( CRC_Errors );
IF Use_CRC THEN
Display_Receive_Error('CRC error')
ELSE
Display_Receive_Error('Checksum error');
END (* Checksum/CRC error *)
END (* Correct sector found *)
ELSE
IF ( Sector_Number = Sector_Prev ) THEN
BEGIN (* Duplicate sector *)
BS_Flag := Receive_Xmodem_Sector( Use_CRC_2 );
IF Do_ACKs THEN
BEGIN
Async_Send( CHR( ACK ) );
IF Do_WXModem THEN
Async_Send( CHR( Sector_Number AND 3 ) )
ELSE IF Do_SeaLink THEN
BEGIN
Async_Send( CHR( Sector_Number ) );
Async_Send( CHR( Sector_Comp ) );
END;
END;
Display_Receive_Error('Duplicate block');
Resend_Errors := SUCC( Resend_Errors );
Error_Flag := FALSE;
Dup_Block := TRUE;
END (* Duplicate sector *)
ELSE
BEGIN (* Out of sequence sector *)
BS_Flag := Receive_Xmodem_Sector( Use_CRC_2 );
IF ( Flush_Count > 0 ) THEN
BEGIN
Flush_Count := PRED( Flush_Count );
Display_Receive_Error('Re-synchronizing ... ');
Error_Flag := FALSE;
END
ELSE
BEGIN
Display_Receive_Error('Synchronization error');
BlockN_Errors := SUCC( BlockN_Errors );
END;
END (* Out of sequence sector *);
END (* Sector # and complement match *)
ELSE
BEGIN (* Sector # and complement do not match *)
Display_Receive_Error('Sector number error');
Comple_Errors := SUCC( Comple_Errors );
END (* Sector # and complement do not match *);
END (* SOH Found *)
ELSE IF ( Initial_Ch = EOT ) THEN
BEGIN
IF ( Do_SeaLink AND ( Sector_Count = 0 ) ) THEN
Null_File_Name := TRUE;
END
ELSE
BEGIN
Display_Receive_Error('SOH not found');
SOH_Errors := SUCC( SOH_Errors );
END;
(* Process bad blocks here *)
IF Error_Flag THEN
BEGIN
(* Increment error count *)
Error_Count := SUCC( Error_Count );
(* If not windowing, flush buffer. *)
IF( NOT ( Do_WXmodem OR Do_SeaLink ) ) THEN
Async_Purge_Buffer;
(* Send negative acknowledge to reject *)
(* bad sector. *)
Async_Send( CHR( NAK ) );
(* If windowing, skip remainder of this *)
(* sector, and set up to skip any left *)
(* in this window. *)
IF Do_WXModem THEN
BEGIN
Async_Send( CHR( Sector_Number AND 3 ) );
Block_Start_Set := [ ^V ];
Wait_For_SOH( SOH_Time, Initial_Ch , Stop_Receive );
Block_Start_Set := [ ^A, ^B, ^D, ^V, ^X ];
Flush_Count := WXmodem_Flush;
END
ELSE IF Do_SeaLink THEN
BEGIN
Async_Send( CHR( Sector_Number ) );
Async_Send( CHR( 255 - Sector_Number ) );
Flush_Count := SEALink_Flush;
END;
END;
IF Display_Time THEN
BEGIN
IF ( NOT ( Error_Flag OR Dup_Block ) ) THEN
BEGIN
Time_To_Send := Time_To_Send -
Time_Per_Block * ( Sector_Length SHR 7 );
IF Time_To_Send < 0.0 THEN
Time_To_Send := 0.0;
END;
END;
(* Check for keyboard entry *)
Check_Keyboard_Input;
(* Update status display *)
IF Display_Status THEN
Update_Xmodem_Receive_Display;
UNTIL ( Initial_Ch = EOT ) OR
( Initial_Ch = CAN ) OR
( Stop_Receive ) OR
( Null_File_Name ) OR
( Error_Count > Xmodem_Max_Errors );
(* If serious error or Alt_R hit, *)
(* stop download. *)
IF ( Stop_Receive ) THEN
BEGIN
Cancel_Transfer;
IF Alt_R_Pressed THEN
BEGIN
IF ( NOT Display_Status ) THEN
Flip_Display_Status;
GoToXY( 25 , 10 );
WRITE('Alt-R hit, receive cancelled.');
Write_Log('ALT-R hit, receive cancelled.', TRUE, FALSE);
ClrEol;
END;
END
(* Null file name -- end of batch *)
ELSE IF Null_File_Name THEN
BEGIN
IF ( NOT Display_Status ) THEN
Flip_Display_Status;
GoToXY( 25 , 10 );
WRITE('Null file name received.');
Write_Log('Null file name received.', TRUE, FALSE);
ClrEol;
OK_Transfer := TRUE;
END
(* EOT received, error count OK *)
ELSE IF ( ( Initial_Ch = EOT ) AND ( Error_Count <= Xmodem_Max_Errors ) ) THEN
BEGIN
(* Acknowledge EOT *)
Async_Send( CHR( ACK ) );
(* Write any remaining data in buffer *)
IF Buffer_Pos > 0 THEN
BEGIN
Write_Count := Buffer_Pos;
IF ( ( RFile_Size_2 + Write_Count ) > RFile_Size ) AND
Truncate_File THEN
Write_Count := TRUNC( RFile_Size - Rfile_Size_2 );
W_Count := Write_Count;
Err := Write_File_Handle( XFile_Handle, Write_Buffer^,
Write_Count );
IF ( Err <> 0 ) OR ( Int24Result <> 0 ) OR
( W_Count <> Write_Count ) THEN
BEGIN
IF ( NOT Display_Status ) THEN
Flip_Display_Status;
GoToXY( 25 , 10 );
WRITE('Error in writing to disk, file may be bad.');
ClrEol;
DELAY( One_Second_Delay );
END;
RFile_Size_2 := RFile_Size_2 + Write_Count;
END;
End_Time := TimeOfDay;
IF ( NOT Display_Status ) THEN
Flip_Display_Status;
OK_Transfer := TRUE;
GoToXY( 2 , 10 );
IF RFile_Size > 0.0 THEN
IF RFile_Size <= RFile_Size_2 THEN
BEGIN
RFile_Size_2 := RFile_Size;
WRITE('Reception complete; ');
END
ELSE
BEGIN
WRITE('Reception appears incomplete; ');
OK_Transfer := FALSE;
END
ELSE
WRITE('Reception complete; ');
(* Fix possible wrap around midnight *)
IF End_Time < Start_Time THEN
End_Time := End_Time + 86400.0;
Effective_Rate := End_Time - Start_Time;
IF ( Effective_Rate = 0.0 ) THEN
Effective_Rate := 1.0;
Effective_Rate := RFile_Size_2 / Effective_Rate;
WRITE('transfer rate ',Effective_Rate:6:1,' CPS');
ClrEol;
IF OK_Transfer THEN
Write_Log('Received file ' + FileName , TRUE , FALSE )
ELSE
Write_Log('Received file ' + FileName + ' (appears incomplete)',
TRUE , FALSE );
OK_Transfer := TRUE;
STR( Effective_Rate:6:1 , TName );
Write_Log('Transfer rate was ' + TName + ' CPS' , TRUE, FALSE );
END
ELSE IF ( Initial_Ch = CAN ) THEN
BEGIN
IF ( NOT Display_Status ) THEN
Flip_Display_Status;
GoToXY( 25 , 10 );
WRITE('Transmitter cancelled file transfer.');
Write_Log('Transmitter cancelled file transfer.', TRUE, FALSE);
ClrEol;
Stop_Receive := TRUE;
END
ELSE
BEGIN (* Too many errors -- cancel transfer *)
Cancel_Transfer;
IF ( NOT Display_Status ) THEN
Flip_Display_Status;
GoToXY( 25 , 10 );
WRITE('Receive cancelled -- too many errors');
Write_Log('Receive cancelled -- too many errors', TRUE, FALSE);
ClrEol;
END;
(* Close transferred file *)
Err := Close_File_Handle( XFile_Handle );
I := Int24Result;
(* Set file time and date if Telink *)
(* or Ymodem *)
IF ( File_Date <> 0 ) AND Use_Time_Sent THEN
Set_File_Date_And_Time;
(* Delete file if bad *)
IF ( Evict_Partial_Trans AND ( NOT OK_Transfer ) ) THEN
BEGIN
ASSIGN( XFile_Byte , Full_File_Name );
(*$I-*)
ERASE( XFile_Byte );
(*$I+*)
I := INT24Result;
END;
DELAY( Two_Second_Delay );
(* Remove download buffer *)
IF Long_Buffer THEN
FREEMEM( Write_Buffer , Buffer_Length );
(* Remove XMODEM window *)
Restore_Screen( Saved_Screen );
Reset_Global_Colors;
(* Cursor back on *)
CursorOn;
(* Restore XON/XOFF status *)
Async_Do_XonXoff := Save_XonXoff;
(* Restore status line *)
IF Do_Status_Line THEN
BEGIN
Set_Status_Line_Name( Short_Terminal_Name );
Write_To_Status_Line( Status_Line_Name, 1 );
END;
END (* Receive_Xmodem_File *) ;